/*
 * Copyright (c) 2012 Johan Fylling
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights 
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
 * copies of the Software, and to permit persons to whom the Software is 
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in 
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 
 * THE SOFTWARE.
 */

part of engine;


class ReadOnlyInventory {
  final Set<int>         _content        = new Set<int>();
  final Map<String, int> _equipmentSlots = new Map<String, int>();
  
  ReadOnlyInventory ();
  
  ReadOnlyInventory.copy (Inventory other) {
    _content.addAll(other._content);
  }
  
  Set<int> get content => new Set<int>.from(_content);
  
  bool get isEmpty => _content.isEmpty;
  
  bool contains (int item) {
    return _content.contains(item);
  }
  
  bool isEquiped (String slot) {
    return _equipmentSlots.containsKey(slot) ? _equipmentSlots[slot] != 0 : false;
  }
  
  int getEquiped (String slot) {
    return _equipmentSlots.containsKey(slot) ? _equipmentSlots[slot] : 0;
  }
}


class Inventory extends ReadOnlyInventory {
  Inventory () : super();
  
  Inventory.copy (Inventory other) : super.copy(other);
  
  void add (int item) {
    _content.add(item);
  }
  
  bool setEquiped (String slot, int item) {
    if (_content.contains(item)) {
      _equipmentSlots[slot] = item;
      return true;
    }
    return false;
  }
  
  // Not in ReadOnlyInventory, so we don't leak members.
  toJson () {
    var data = {
      "content": new List<int>.from(_content)
    };
    if (!_equipmentSlots.isEmpty) {
      data["equiped"] = _equipmentSlots;
    }
    return data;
  }
}


class InventoryStorageHandler {
  static void setup (StorageManager manager, Map attributes, Inventory inventory) {
    var content = attributes["content"];
    if (content != null) {
      assert(content is List);
      for (var tag in content) {
        assert(tag is String);
        manager.onTag(tag, (final dynamic obj) {
          assert(obj is WorldObject);
          inventory.add(obj.id);
        });
      }
    }
    
    var equiped = attributes["equiped"];
    if (equiped != null) {
      assert(equiped is Map);
      equiped.forEach((var key, var tag) {
        assert(key is String);
        assert(tag is String);
        manager.onTag(tag, (final dynamic obj) {
          assert(obj is WorldObject);
          inventory.setEquiped(key, obj.id);
        });
      });
    }
  }
}
